
`include "common_header.verilog"

//  ****************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized Reproduction or Use is Expressly Prohibited. 
//  Copyright (c) 2000 MoreThanIP
//  Designed by Francois Balay
//  fbalay@morethanip.com
//  ****************************************************************************
//                               Gray Counter
//  ****************************************************************************
//  Version    : $Id: gray_cnt_sr.v,v 1.1 2011/05/17 10:08:50 dk Exp $
//  ****************************************************************************

module gray_cnt_sr (
   clk,
   reset,
   sreset,
   enable,
   b_out,
   g_out);
   
parameter ADDR_WIDTH = 7;
parameter DEPTH = 128;

input   clk; 
input   reset; 
input   sreset; 
input   enable; 
output  [ADDR_WIDTH - 1:0] b_out; 
output  [ADDR_WIDTH - 1:0] g_out; 
reg     [ADDR_WIDTH - 1:0] b_out; 
reg     [ADDR_WIDTH - 1:0] g_out; 
reg     [ADDR_WIDTH - 1:0] b_int;
wire    [ADDR_WIDTH - 1:0] b_slv; 

wire    [ADDR_WIDTH - 1:0]  gry_grayval; 

always @(posedge clk or posedge reset)
   begin : bin
   if (reset == 1'b 1)
      begin
      b_int <= {{(ADDR_WIDTH-1){1'b0}}, 1'b 1};   // 1	
      end
   else
      begin
      if (sreset==1'b1)
         begin
         b_int <= {{(ADDR_WIDTH-1){1'b0}}, 1'b 1};
         end
      else
         begin
         if (enable == 1'b 1)
            begin
            if (b_int < {(ADDR_WIDTH){1'b 1}}) // (DEPTH - 1))
               begin
               b_int <= (b_int + {{(ADDR_WIDTH-1){1'b0}}, 1'b 1});	
               end
            else
               begin
               b_int <= {(ADDR_WIDTH){1'b 0}};	
               end
            end
         end
      end
   end

assign b_slv = b_int; //  conv_std_logic_vector(b_int, ADDR_WIDTH);

//  Binary next generation to run according the gray values
//  -------------------------------------------------------

always @(posedge clk or posedge reset)
   begin : binreg
   if (reset == 1'b 1)
      begin
      b_out <= {(ADDR_WIDTH){1'b 0}};	
      end
   else
      begin
      if (sreset==1'b1)
         begin
         b_out <= {(ADDR_WIDTH){1'b 0}};
         end
      else
         begin
         if (enable == 1'b 1)
            begin
            b_out <= b_slv;	
            end
         end
      end
   end

//  Binary to Gray Code conversion with additional Registers
//  --------------------------------------------------------

assign gry_grayval = bin2gray(b_slv) ;

always @(posedge clk or posedge reset)
   begin : gry
   if (reset == 1'b 1)
      begin
      g_out <= {(ADDR_WIDTH){1'b 0}};	
      end
   else
      begin
      if (sreset==1'b1)
         begin
         g_out <= {(ADDR_WIDTH){1'b 0}};
         end
      else
         begin
         if (enable == 1'b 1)
            begin 
            g_out <= gry_grayval;	
            end
         end
      end
   end

// Binary to Gray Conversion
// -------------------------

function [ADDR_WIDTH-1:0] bin2gray;

        input [ADDR_WIDTH-1:0]  bin_val ;
        
        integer LOOP_INDEX; 
                
        for (LOOP_INDEX = 0; LOOP_INDEX <= ADDR_WIDTH - 1; LOOP_INDEX = LOOP_INDEX + 1)
        begin
            
                if (LOOP_INDEX == ADDR_WIDTH - 1)
                begin
               
                        bin2gray[LOOP_INDEX] = bin_val[LOOP_INDEX];	
               
                end
                else
                begin
               
                        bin2gray[LOOP_INDEX] = bin_val[LOOP_INDEX + 1] ^ bin_val[LOOP_INDEX];	
               
                end
        
        end
        
endfunction

`ifdef MTIP_XSYNC_DISPLAY
initial $display("gray_cnt_sr:%m.g_out[%0d:0]",ADDR_WIDTH-1);
`endif

endmodule // module gray_cnt
